package com.tomvian.audio 
{
	import com.tomvian.tools.OmniTick;
	import flash.events.Event;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	/**
	 * AudioTrack
	 * @author Tom Vian
	 */
	public class AudioTrack
	{
		//--------------------------------------------------------------------------
		//
		//  Properties
		//
		//--------------------------------------------------------------------------
		
		protected var _volume:Number = 1.0;
		
		protected var _audioList:AudioList;
		
		protected var _currentAudioID:int = -1;
		
		protected var _currentAudio:AudioChannel;
		protected var _previousAudio:AudioChannel;
		
		protected var _positions:Array = [];
		
		protected var _audioClassList:Array;
		protected var _audioClassListVolume:Number;
		
		//--------------------------------------------------------------------------
		//
		//  Getters / Setters
		//
		//--------------------------------------------------------------------------
		
		public function get volume():Number { return _volume; }
		public function set volume(value:Number):void 
		{
			_volume = value;
			_currentAudio.volume = _volume;
		}
		
		//--------------------------------------------------------------------------
		//
		//  Constructor
		//
		//--------------------------------------------------------------------------
		
		public function AudioTrack(audioList:AudioList = null) 
		{
			_audioList = audioList;
			_currentAudio = new AudioChannel(this);
			_previousAudio = new AudioChannel(this);
		}
		
		//--------------------------------------------------------------------------
		//
		//  Methods
		//
		//--------------------------------------------------------------------------
		
		public function playShortAudio(audioID:uint, volume:Number = 1.0, startTime:uint = 0):void
		{
			var audioClass:Class = _audioList.audio[audioID];
			if (audioClass)
			{
				var sound:Sound = new audioClass;
				var soundTransform:SoundTransform = new SoundTransform(volume * _volume * _audioList.volumes[audioID]);
				sound.play(startTime, 0, soundTransform);
			}
		}
		
		public function playShortAudioClass(audioClass:Class, volume:Number = 1.0, startTime:uint = 0):SoundChannel
		{
			var sound:Sound = new audioClass;
			var soundTransform:SoundTransform = new SoundTransform(volume * _volume);
			return sound.play(startTime, 0, soundTransform)
		}
		
		public function playShortAudioClassList(audioClassList:Array, volume:Number = 1.0):void
		{
			var soundChannel:SoundChannel;
			
			if (_audioClassList && _audioClassList.length > 0)
			{
				soundChannel = _audioClassList[0];
				soundChannel.removeEventListener(Event.SOUND_COMPLETE, onAudioClassListComplete);
				soundChannel.stop();
			}
			
			_audioClassList = audioClassList;
			_audioClassListVolume = volume;
			
			var audioClass:Class = _audioClassList[0];
			soundChannel = playShortAudioClass(audioClass, _audioClassListVolume)
			soundChannel.addEventListener(Event.SOUND_COMPLETE, onAudioClassListComplete);
			_audioClassList[0] = soundChannel;
		}
		
		public function playLongAudio(audioID:uint, volume:Number = 1.0, crossFadeTime:Number = 0.0, loops:int = int.MAX_VALUE, rememberPosition:Boolean = false, startTime:uint = 0):void
		{
			if (audioID == _currentAudioID) return;
			
			var audioClass:Class = _audioList.audio[audioID];
			
			if (audioClass)
			{
				var newAudio:Sound = new audioClass;
				
				volume *= _audioList.volumes[audioID];
				
				if (rememberPosition) startTime = uint(_positions[audioID]);
				
				_currentAudioID = audioID;
				
				_previousAudio.stop();
				
				if (crossFadeTime != 0.0)
				{
					if(_currentAudio.channel)
					{
						_previousAudio.transferSoundFrom(_currentAudio);
						_previousAudio.fadeToVolume(0.0, crossFadeTime);
					}
					
					_currentAudio.play(newAudio, volume, loops, startTime);
					_currentAudio.volume = 0.0;
					_currentAudio.fadeToVolume(volume, crossFadeTime);
					
					OmniTick.tick.onTick.remove(onTick);
					OmniTick.tick.onTick.add(onTick);
				}
				else
				{
					_currentAudio.stop();
					_currentAudio.play(newAudio, volume, loops, startTime);
				}
			}
		}
		
		public function storeLongAudioPosition():void
		{
			_positions[_currentAudioID] = uint(_currentAudio.position);
		}
		
		public function fadeLongAudio(volume:Number = 1.0, fadeTime:Number = 0.0):void
		{
			_currentAudio.fadeToVolume(volume, fadeTime);
			
			OmniTick.tick.onTick.remove(onTick);
			OmniTick.tick.onTick.add(onTick);
		}
		
		private function onTick():void
		{
			var previous:Boolean = _previousAudio.fadeTick();
			var current:Boolean = _currentAudio.fadeTick();
			
			if(!previous && !current) OmniTick.tick.onTick.remove(onTick);
		}
		
		private function onAudioClassListComplete(e:Event):void
		{
			var soundChannel:SoundChannel = e.target as SoundChannel;
			soundChannel.removeEventListener(Event.SOUND_COMPLETE, onAudioClassListComplete);
			
			_audioClassList.shift();
			
			if (_audioClassList.length > 0)
			{
				var audioClass:Class = _audioClassList[0];
				soundChannel = playShortAudioClass(audioClass, _audioClassListVolume)
				soundChannel.addEventListener(Event.SOUND_COMPLETE, onAudioClassListComplete);
				_audioClassList[0] = soundChannel;
			}
			else
			{
				_audioClassList = null;
			}
		}
	}
}